两个数据源工厂类
UnpooledDataSourceFactory
1 |
|
PooledDataSourceFactory
1 | public class PooledDataSourceFactory extends UnpooledDataSourceFactory { |
PooledDataSourceFactory 继承UnpooledDataSourceFactory 只是返回数据源为PooledDataSource,其他属性配置不变
UnpooledDataSource 获取连接
1 |
|
上面就是UnpooledDataSource 获取连接逻辑,即每次会新增一连接,创建连接通常会很耗时,并且连接资源很宝贵,所以连接需要交给连接池管理,Mybatis也有连接池的实现即PooledDataSource
PooledDataSource
PooledDataSource,PoolState,PooledConnection三者关系为下图
PooledDataSource 由UnpooledDataSource创建,并且自身不维护连接,只管理PooledConnection,但是由于是连接池所以还需要维护连接池大小,状态,可用连接等,所以有PoolState
PooledConnection
它主要是用来管理数据库连接的,它是一个代理类,实现了 InvocationHandler 接口,由于实现InvocationHandler,查看invoke方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32class PooledConnection implements InvocationHandler {
private static final String CLOSE = "close";
private static final Class<?>[] IFACES = new Class[]{Connection.class};
private final int hashCode;
private final PooledDataSource dataSource;
private final Connection realConnection; //真正的数据库连接
private final Connection proxyConnection; //代理对象
private long checkoutTimestamp; //最后一次取出时间
private long createdTimestamp;//创建实际戳
private long lastUsedTimestamp;//最后使用时间戳
private int connectionTypeCode;
private boolean valid;//是否有效
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
//如果是关闭连接则会放回连接池
if ("close".hashCode() == methodName.hashCode() && "close".equals(methodName)) {
this.dataSource.pushConnection(this);
return null;
} else {
try {
if (!Object.class.equals(method.getDeclaringClass())) {
this.checkConnection();
}
return method.invoke(this.realConnection, args);
} catch (Throwable var6) {
throw ExceptionUtil.unwrapThrowable(var6);
}
}
}
}
PoolState
PoolState 类主要是用来管理连接池的状态,比如哪些连接是空闲的,哪些是活动的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class PoolState {
protected PooledDataSource dataSource;
//空闲连接
protected final List<PooledConnection> idleConnections = new ArrayList();
//活动连接
protected final List<PooledConnection> activeConnections = new ArrayList();
//请求数据库连接的次数
protected long requestCount = 0L;
//累计时间
protected long accumulatedRequestTime = 0L;
protected long accumulatedCheckoutTime = 0L;
protected long claimedOverdueConnectionCount = 0L;
protected long accumulatedCheckoutTimeOfOverdueConnections = 0L;
protected long accumulatedWaitTime = 0L;
protected long hadToWaitCount = 0L;
protected long badConnectionCount = 0L;
}
PooledDataSource 获取连接
1 | public Connection getConnection() throws SQLException { |
首先获取的代理数据库连接PooledConnection,该对象通过维护真是Connection,并通过JDK的动态代理产生真实的数据库Connection连接对象
循环获取PooledConnection,知道获取得到为止
首先拿到连接池状态锁,判断空闲连接池是否为空,如果不为空,获取第一个空闲连接(同时remove从空闲池集合中remove第一个),并返回
如果空闲连接池为空,判断当前激活连接池大小是否小于连接池最大连接数,如果小于则new一个新的PooledConnection代理连接对象
如果连接池最大连接数已满,获取第一个连接池代理对象,判断该代理对象是否预期(连接池预期时间默认20秒),如果当前连接已预期,从活动连接池中移除该连接,回滚当前连接事务,使用当前代理对象的Connection,作为创建新的PooledConnection对象的参数,老的连接置为不可用
如果第一个池对象并未预期,则等待,根据连接池的等待时间进行等待
拿到PooledConnection对象后,对当前连接判断是否有效,有效的方法验证主要包括当前连接是否关闭,如果只想query操作,并执行,执行拿到结果则当前连接为可用连接
拿到真实Connection对象,判断是否自动提交,如果为false,则回滚当前Connection的事务,最后将该连接加入到连接池活动连接集合中返回
当我们得到PooledConnection后,因为最终要返回的是Connection对象,随意调用池代理连接的getProxyConnect()方法获取代理对象
获取代理对象时,首先判断当前Connection的方法,如果是调用close()方法,则首先会进入释放连接的逻辑,从当前活动连接池中移除该对象,判断空闲池空间足够,如果可用,加入空闲连接池,调用notifyAll(),唤醒wait线程,如果空闲连接池已满,则真实调用Connection的close()方法,并在之前回滚事务,关闭该连接